<?php
if(!function_exists('json_encode'))
{
    include_once('JSON.php');
    $GLOBALS['JSON_OBJECT'] = new Services_JSON();
    function json_encode($value)
    {
        return $GLOBALS['JSON_OBJECT']->encode($value);
    }

    function json_decode($value)
    {
        return $GLOBALS['JSON_OBJECT']->decode($value);
    }
}

if(!function_exists('stripos')) {
  function stripos($haystack,$needle) {
    return strpos(strtoupper($haystack),strtoupper($needle));
  }
}

if(function_exists('date_default_timezone_set')) {
    date_default_timezone_set('Asia/Shanghai');
}

menu_register(array(
	'' => array(
		'callback' => 'twitter_home_page',
		'accesskey' => '0',
	),
	'status' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_status_page',
	),
	'update' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_update',
	),
	'replies' => array(
		'security' => true,
		'callback' => 'twitter_replies_page',
		'accesskey' => '1',
		'title' => __("Replies"),
	),
	'retweets' => array(
		'security' => true,
		'callback' => 'twitter_retweets_page',
		'accesskey' => '2',
		'title' => __("Retweets"),
	),
	'twitter-retweet' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_retweet',
	),
	'favourite' => array(
		'hidden'=> true,
		'security' => true,
		'callback' => 'twitter_mark_favourite_page',
	),
	'unfavourite' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_mark_favourite_page',
	),
	'directs' => array(
		'security' => true,
		'callback' => 'twitter_directs_page',
		'accesskey' => '3',
		'title' => __("Directs"),
	),
	'search' => array(
		'security' => true,
		'callback' => 'twitter_search_page',
		'accesskey' => '4',
		'title' => __("Search"),
	),
	'public' => array(
		'security' => true,
		'callback' => 'twitter_public_page',
		'title' => __("Public"),
	),
	'user' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_user_page',
	),
	'follow' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_follow_page',
	),
	'unfollow' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_follow_page',
	),
	'confirm' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_confirmation_page',
	),
	'block' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_block_page',
	),
	'unblock' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_block_page',
	),
	'favourites' => array(
		'security' => true,
		'callback' =>	'twitter_favourites_page',
		'title' => __("Favourites"),
	),
	'followers' => array(
		'security' => true,
		'callback' => 'twitter_followers_page',
		'title' => __("Followers"),
	),
	'friends' => array(
		'security' => true,
		'callback' => 'twitter_friends_page',
		'title' => __("Friends"),
	),
	'blockings' => array(
		'security' => true,
		'security' => true,
		'callback' => 'twitter_blockings_page',
		'title' => __("Blockings"),
	),
	'delete' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_delete_page',
	),
	'retweet' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_retweet_page',
	),
	'flickr' => array(
		'security' => true,
		'hidden' => true,
		'callback' => 'generate_thumbnail',
	),
	'mobypicture' => array(
		'security' => true,
		'hidden' => true,
		'callback' => 'generate_thumbnail',
	), 
	'moblog' => array(
		'security' => true,
		'hidden' => true,
		'callback' => 'generate_thumbnail',
	),
	'hash' => array(
		'security' => true,
		'hidden' => true,
		'callback' => 'twitter_hashtag_page',
	),
	'twitpic' => array(
		'security' => true,
		'callback' => 'twitter_twitpic_page',
		'title' => __("Twitpic"),
	),
	'profile' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_profile_page',
	),
	'trends' => array(
		'security' => true,
		'callback' => 'twitter_trends_page',
		'title' => __("Trends"),
	),
	'lists' => array(
		'security' => true,
		'callback' => 'lists_controller',
		'title' => __("Lists"),
	),
	'spam' => array(
		'hidden' => true,
		'security' => true,
		'callback' => 'twitter_spam_page',
),
));

function sysSubStr($String,$Length,$Append = false) {
    if (mb_strlen($String,'UTF-8') <= $Length ){
        return $String;
    } else {
        $I = 0;
		$J = 0;
		if($Append){
			$J = 3;
		}
        while ($J < $Length) {
            $StringTMP = substr($String,$I,1);
            if (ord($StringTMP)>=224 ) {
                $StringTMP = substr($String,$I,3);
                $I = $I + 3;
            } elseif(ord($StringTMP)>=192 ) {
                $StringTMP = substr($String,$I,2);
                $I = $I + 2;
            } else {
                $I = $I + 1;
            }
			$J = $J + 1;
            $StringLast[] = $StringTMP;
        }
        $StringLast = implode("",$StringLast);
        if($Append) {
            $StringLast .= "...";
        }
        return $StringLast;
    }
} 

function lists_paginated_process($url) {
	$cursor = $_GET['cursor'];
	if (!is_numeric($cursor)) {
		$cursor = -1;
	}
	$url .= '?cursor='.$cursor;
	$xml = twitter_process($url);
	return simplexml_load_string($xml);
}

function twitter_lists_tweets($user, $list) {
	$url = NETPUTWEETS_API."{$user}/lists/{$list}/statuses.json";
	$page = intval($_GET['page']);
	if ($page > 0) $url .= '?page='.$page;
	return twitter_process($url);
}

function twitter_lists_user_lists($user) {
	return lists_paginated_process(NETPUTWEETS_API."{$user}/lists.xml");
}

function twitter_lists_user_memberships($user) {
	return lists_paginated_process(NETPUTWEETS_API."{$user}/lists/memberships.xml");
}

function twitter_lists_list_members($user, $list) {
	return lists_paginated_process(NETPUTWEETS_API."{$user}/{$list}/members.xml");
}

function twitter_lists_list_subscribers($user, $list) {
	return lists_paginated_process(NETPUTWEETS_API."{$user}/{$list}/subscribers.xml");
}

function lists_controller($query) {
	$user = $query[1];
	if (!$user) $user = user_current_username();
	if ($query[3]) {
		$method = $query[3];
		$list = $query[2];
	} else {
		$method = $query[2];
	}
	switch ($method) {
		case '':
		case 'lists':
			return lists_lists_page($user);
		case 'memberships':
			return lists_membership_page($user);
		case 'members':
			return lists_list_members_page($user, $list);
		case 'subscribers':
			return lists_list_subscribers_page($user, $list);
		case 'edit':
			break;
		default:
			$list = $method;
			return lists_list_tweets_page($user, $list);
	}
	return theme(__("Error"), __("List page not found"));
}

function lists_lists_page($user) {
	$lists = twitter_lists_user_lists($user);
	$content = "<p><a href='".BASE_URL."lists/{$user}/memberships'>Lists following {$user}</a> | <strong>{$user} 's Lists</strong></p>";
	$content .= theme('lists', $lists);
	theme('page', "{$user} 's Lists", $content);
}

function lists_membership_page($user) {
	$lists = twitter_lists_user_memberships($user);
	$content = "<p><strong>Lists following {$user}</strong> | <a href='".BASE_URL."lists/{$user}'>{$user} 's Lists</a></p>";
	$content .= theme('lists', $lists);
	theme('page', "Lists following {$user}", $content);
}

function lists_list_tweets_page($user, $list) {
	$tweets = twitter_lists_tweets($user, $list);
	$tl = twitter_standard_timeline($tweets, 'public');
	$content = theme('status_form');
	$list_url = "lists/{$user}/{$list}";
 	$content .= "<p><a href='".BASE_URL."user/{$user}'>{$user}</a>/<strong>{$list}</strong> 's Tweets | <a href='".BASE_URL."{$list_url}/members'>View Members</a> | <a href='".BASE_URL."{$list_url}/subscribers'>View Subscribers</a></p>";
	$content .= theme('timeline', $tl);
	theme('page', "Lists {$user}/{$list}", $content);
}

function lists_list_members_page($user, $list) {
	$p = twitter_lists_list_members($user, $list);
	$content = theme('followers', $p, 1);
	$content .= theme('list_pagination', $p);
	theme('page', "Members of {$user}/{$list}", $content);
}
 
function lists_list_subscribers_page($user, $list) {
	$p = twitter_lists_list_subscribers($user, $list);
	$content = theme('followers', $p, 1);
 	$content .= theme('list_pagination', $p);
	theme('page', "Subscribers of {$user}/{$list}", $content);
}


function theme_lists($json) {
	if (count($json->lists) == 0) {
		return "<p>".__("No lists to display")."</p>";
	}
	$rows = array();
	$headers = array('Lists', 'Members', 'Subscribers');
	foreach ($json->lists->list as $list) {
		$url = "lists/{$list->user->screen_name}/{$list->slug}";
		$rows[] = array(
			"<a href='".BASE_URL."user/{$list->user->screen_name}'>{$list->user->screen_name}</a>/<a href='".BASE_URL."{$url}'><strong>{$list->slug}</strong></a>",
			"<a href='".BASE_URL."{$url}/members'>{$list->member_count}</a>",
			"<a href='".BASE_URL."{$url}/subscribers'>{$list->subscriber_count}</a>",
		);
	}
	$content = theme('table', $headers, $rows);
	$content .= theme('list_pagination', $json);
	return $content;
}

function theme_list_pagination($json) {
	if ($cursor = (string) $json->next_cursor) {
		$links[] = "<a href='".BASE_URL."{$_GET['q']}?cursor={$cursor}'>".__("Older")."</a>";
	}
	if ($cursor = (string) $json->previous_cursor) {
		$links[] = "<a href='".BASE_URL."{$_GET['q']}?cursor={$cursor}'>".__("Newer")."</a>";
	}
	if (count($links) > 0) return '<p>'.implode(' | ', $links).'</p>';
}

function long_url($shortURL){
	$url = "http://api.longurl.org/v2/expand?format=json&url=" . $shortURL;
	$curl_handle=curl_init();
	curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
	curl_setopt($curl_handle,CURLOPT_URL,$url);
	$url_json = curl_exec($curl_handle);
	curl_close($curl_handle);
	$url_array = json_decode($url_json,true);
	$url_long = $url_array["long-url"];
	return $url_long;
}

function friendship_exists($user_a) {
	$request = 'http://twitter.com/friendships/show.json?target_screen_name=' . $user_a;
	$following = twitter_process($request);
	if ($following->relationship->target->following == 1) {
		return true;
	} else {
		return false;
	}
}

function twitter_block_exists($query) {
	$request = NETPUTWEETS_API.'blocks/blocking/ids.json';
	$blocked = (array) twitter_process($request);
	return in_array($query,$blocked);
}

function twitter_trends_page($query) {
	$trend_type = $query[1];
	if($trend_type == '') $trend_type = 'current';
	$request = NETPUTWEETS_APIS.'trends/' . $trend_type . '.json';
	$trends = twitter_process($request);
	$search_url = 'search?query=';
	foreach($trends->trends as $temp) {
		foreach($temp as $trend) {
			$row = array('<strong><a href="'.BASE_URL. $search_url . urlencode($trend->query) . '">' . $trend->name . '</a></strong>');
			$rows[] = $row;
		}
	}
	$headers = array('<p><a href="'.BASE_URL.'trends">'.__("Current").'</a> | <a href="'.BASE_URL.'trends/daily">'.__("Daily").'</a> | <a href="'.BASE_URL.'trends/weekly">'.__("Weekly").'</a></p>');
	$content = theme('table', $headers, $rows, array('class' => 'timeline'));
	theme('page', __("Trends"), $content);
}

function js_counter($name) {
	$script = '<script type="text/javascript">
	function updateCount() {
		document.getElementById("remaining").innerHTML = 140 - document.getElementById("' . $name . '").value.length;
		setTimeout(updateCount, 400);
	}
	updateCount();
</script>';
	return $script;
}

function twitter_twitpic_page($query) {
	if (user_type() == 'oauth') {
		return theme('page', __("Error"), '<p>'.__("You can\'t use Twitpic uploads while accessing Dabr using an OAuth login.").'</p>');
	}
	if ($_POST['message']) {
	$response = twitter_process('http://twitpic.com/api/uploadAndPost', array(
		'media' => '@'.$_FILES['media']['tmp_name'],
		'message' => stripslashes($_POST['message']),
		'username' => user_current_username(),
		'password' => $GLOBALS['user']['password'],
	));
	if (preg_match('#mediaid>(.*)</mediaid#', $response, $matches)) {
		$id = $matches[1];
		twitter_refresh('twitpic/confirm/$id');
	} else {
		twitter_refresh('twitpic/fail');
	}
	} elseif ($query[1] == 'confirm') {
	$content = "<p>".__("Upload success.")."</p><p><img src='http://twitpic.com/show/thumb/{$query[2]}' alt='' /></p>";
	} elseif ($query[1] == 'fail') {
	$content = '<p>'.__("Twitpic upload failed. No idea why!").'</p>';
	} else {
	$content = '<form method="post" action="'.BASE_URL.'twitpic" enctype="multipart/form-data">'.__("Image").' <input type="file" name="media" /><br />'.__("Message").': <input type="text" name="message" maxlength="120" /><br /><input type="submit" value="'.__("Upload").'" /></form>';
	}
	return theme('page', __("Twitpic Upload"), $content);
}

function twitter_profile_page($query) {
	$url = NETPUTWEETS_API."account/update_profile.json";
	if ($_POST['name']) {
		$post_data = array(
			'name' => stripslashes($_POST['name']),
			'location' => $_POST['location'],
			'url' => $_POST['url'],
			'description' => $_POST['description'],
		);
		$p = twitter_process($url, $post_data);
		$user = user_current_username();
		twitter_refresh("user/{$user}");
	} else {
		$p = twitter_process($url, $post_data);
		$content = "<form method=\"post\" action=\"".BASE_URL."profile\" enctype=\"multipart/form-data\">".__("Name")." <input type=\"text\" name=\"name\" value=\"{$p->name}\" /> (Max 20) <br />".__("Location")." <input type=\"text\" name=\"location\" value=\"{$p->location}\" /> (Max 30) <br />".__("Link")." <input type=\"text\" name=\"url\" value=\"{$p->url}\" /> (Max 100) <br />".__("Bio")." (Max 160) <br /><textarea name=\"description\" style=\"width:95%\" rows=\"3\" id=\"description\" >{$p->description}</textarea><br /><input type=\"submit\" value=\"".__("Update")."\" /></form>";
	}
	$p = twitter_process($url, $post_data);
	return theme('page', __("Update Profile"), $content);
}

function twitter_process($url, $post_data = false) {
	if ($post_data === true) $post_data = array();
	if (user_type() == 'oauth' && strpos($url, '/twitter.com') !== false) {
	user_oauth_sign($url, $post_data);
	} elseif (strpos($url, 'twitter.com') !== false && is_array($post_data)) {
	// Passing $post_data as an array to twitter.com (non-oauth) causes an error :(
	$s = array();
	foreach ($post_data as $name => $value)
		$s[] = $name.'='.urlencode($value);
	$post_data = implode('&', $s);
	}
	$ch = curl_init($url);
	if($post_data !== false && !$_GET['page']) {
	curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Expect:'));
	curl_setopt ($ch, CURLOPT_POST, true);
	curl_setopt ($ch, CURLOPT_POSTFIELDS, $post_data);
	}
	if (user_type() != 'oauth' && user_is_authenticated())
	curl_setopt($ch, CURLOPT_USERPWD, user_current_username().':'.$GLOBALS['user']['password']);
	curl_setopt($ch, CURLOPT_VERBOSE, 0);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_TIMEOUT, 30);
	curl_setopt($ch, CURLOPT_USERAGENT, 'dabr');
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
#    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
	$response = curl_exec($ch);
	$response_info=curl_getinfo($ch);
	curl_close($ch);
	switch( intval( $response_info['http_code'] ) ) {
	case 200:
		$json = json_decode($response);
		if ($json) return $json;
		return $response;
	/*case 401:
		user_logout();
        theme('error', '<p>'.__("Error: Login credentials incorrect.").'</p>');*/
	case 0:
		theme('error', '<h3>Twitter timed out</h3><p>Dabr gave up on waiting for Twitter to respond. They\'re probably overloaded right now, try again in a minute.</p>');
	default:
		$result = json_decode($response);
		$result = $result->error ? $result->error : $response;
		if (strlen($result) > 500) $result = 'Something broke.';
		theme('error', "<h3>".__("An error occured while calling the API")."</h3><p>{$response_info['http_code']}: {$result}</p><hr><p>$url</p>");
	}
}

function twitter_url_shorten($text) {
	if (!defined('BITLY_API_KEY')) return $text;
	return preg_replace_callback('#((\w+://|www)[\w\#$%&~/.\-;:=,?@\[\]+]{33,1950})(?<![.,])#is', 'twitter_url_shorten_callback', $text);
}

/* function twitter_url_shorten_callback($match) {
	if (preg_match('#http://www.flickr.com/photos/[^/]+/(\d+)/#', $match[0], $matches)) {
		return 'http://flic.kr/p/'.flickr_encode($matches[1]);
	}
	if (setting_fetch('short') == 'no') {
		return $match;
	} elseif (setting_fetch('short', 'is.gd') == 'is.gd') {
		$request = 'http://is.gd/api.php?longurl='.urlencode($match[0]);
		$links = twitter_fetch($request);
		if (substr($links,0,13) == 'http://is.gd/') {
			return $links;
		} else {
			return $match;
		}
		return twitter_fetch($request);
	} elseif (setting_fetch('short') == 'tr.im') {
		$request = 'http://api.tr.im/api/trim_simple?url='.urlencode($match[0]);
		$links = twitter_fetch($request);
		if (substr($links,0,13) == 'http://tr.im/') {
			return $links;
		} else {
			return $match;
		}
	} elseif (setting_fetch('short') == 'tinyurl.com') {
		$request = 'http://tinyurl.com/api-create.php?url='.urlencode($match[0]);
		$links = twitter_fetch($request);
		if (substr($links,0,19) == 'http://tinyurl.com/') {
			return $links;
		} else {
			return $match;
		}
	} elseif (setting_fetch('short') == 'r.im') {
		$request = 'http://r.im/api/index.cfm?long_url='.urlencode($match[0]);
		$links = twitter_fetch($request);
		if (substr($links,0,12) == 'http://r.im/') {
			return $links;
		} else {
			return $match;
		}
	} elseif (setting_fetch('short') == 'j.mp') {
		if (!defined('BITLY_API_KEY')) return $match[0];
		$request = 'http://api.j.mp/shorten?version=2.0.1&longUrl='.urlencode($match[0]).'&login='.BITLY_LOGIN.'&apiKey='.BITLY_API_KEY;
		$json = json_decode(twitter_fetch($request));
		if ($json->errorCode == 0) {
			$results = (array) $json->results;
			$result = array_pop($results);
			return $result->shortUrl;
		} else {
			return $match[0];
		}
	} elseif (setting_fetch('short') == 'goo.gl') {
		$request = 'http://ggl-shortener.appspot.com/?url='.urlencode($match[0]);
		$json = json_decode(twitter_fetch($request));//lzq
		if (!isset($json->error_message)) {
			return $json->short_url;
		} else {
			return $match[0];
		}
	}
} */

function twitter_url_shorten_callback($match) {
	if (preg_match('#http://www.flickr.com/photos/[^/]+/(\d+)/#', $match[0], $matches)) {
		return 'http://flic.kr/p/'.flickr_encode($matches[1]);
	}
	if (setting_fetch('short') == 'j.mp') {
		if (!defined('BITLY_API_KEY')) return $match[0];
		$request = 'http://api.j.mp/shorten?version=2.0.1&longUrl='.urlencode($match[0]).'&login='.BITLY_LOGIN.'&apiKey='.BITLY_API_KEY;
		$json = json_decode(twitter_fetch($request));
		if ($json->errorCode == 0) {
			$results = (array) $json->results;
			$result = array_pop($results);
			return $result->shortUrl;
		} else {
			return $match[0];
		}
	} elseif (setting_fetch('short') == 'goo.gl') {
		$request = 'http://ggl-shortener.appspot.com/?url='.urlencode($match[0]);
		$json = json_decode(twitter_fetch($request));//lzq
		if (!isset($json->error_message)) {
			return $json->short_url;
		} else {
			return $match[0];
		}
	} else {
		$short_url_mapping = array(
			'is.gd' => 'http://is.gd/api.php?longurl=',
			'tr.im' => 'http://api.tr.im/api/trim_simple?url=',
			'tinyurl.com' => 'http://tinyurl.com/api-create.php?url=',
			'r.im' => 'http://r.im/api/index.cfm?long_url=',
		);
		foreach ($short_url_mapping as $setting => $url) {
			if (setting_fetch('short') == $setting) {
				$request = $url.urlencode($match[0]);
				$links = twitter_fetch($request);
				if (stripos($links, 'http://'.$setting) == 0) return $links;
			}
		}
		return $match;
	}
}

function twitter_fetch($url) {
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_TIMEOUT, 10);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$response = curl_exec($ch);
	curl_close($ch);
	return $response;
}

function twitter_parse_links_callback($matches) {
	$url = $matches[1];
	if ((substr($url, 0, strlen(BASE_URL)) == BASE_URL) || (substr($url,0,19) == 'http://twitpic.com/')) return "<a href='$url'>$url</a>";
	if (setting_fetch('gwt') == 'on') {
		$encoded = urlencode($url);
		return "<a href='http://google.com/gwt/n?u={$encoded}'>{$url}</a>";
	} else {
		return theme('external_link', $url);
	}
}

function twitter_parse_tags($input) {
	$out = preg_replace_callback('#(\w+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)(?<![.,])#is', 'twitter_parse_links_callback', $input);
	$out = preg_replace('#(^|\s)@([a-z_A-Z0-9]+)/([\w\d-]+)#', '$1@<a href="user/$2">$2</a>/<a href="lists/$2/$3">$3</a>', $out);
	$out = preg_replace('#(^|\s)@([a-z_A-Z0-9]+)#', '$1@<a href="user/$2">$2</a>', $out);
	$out = preg_replace('#(^|\s)(\\#([a-z_A-Z0-9:_-]+))#', '$1<a href="hash/$3">$2</a>', $out);
	if (setting_fetch('showthumbs', 'yes') == 'yes') {
		$out = twitter_photo_replace($out);
	}
	return $out;
}

function flickr_decode($num) {
	$alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
	$decoded = 0;
	$multi = 1;
	while (strlen($num) > 0) {
		$digit = $num[strlen($num)-1];
		$decoded += $multi * strpos($alphabet, $digit);
		$multi = $multi * strlen($alphabet);
		$num = substr($num, 0, -1);
	}
	return $decoded;
}

function flickr_encode($num) {
	$alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
	$base_count = strlen($alphabet);
	$encoded = '';
	while ($num >= $base_count) {
		$div = $num/$base_count;
		$mod = ($num-($base_count*intval($div)));
		$encoded = $alphabet[$mod] . $encoded;
		$num = intval($div);
	}
	if ($num) $encoded = $alphabet[$num] . $encoded;
	return $encoded;
}

function twitter_photo_replace($text) {
	$tmp = strip_tags($text);
	if (preg_match_all('#twitgoo.com/([\d\w]+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $match) {
			$text = "<a href='http://twitgoo.com/{$match}'><img src='http://twitgoo.com/show/thumb/{$match}' class='twitpic' /></a><br />".$text;
		}
	}
	if (preg_match_all('#twitpic.com/([\d\w]+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $match) {
			$text = "<a href='http://twitpic.com/{$match}'><img src='http://twitpic.com/show/thumb/$match' class='twitpic' /></a><br />".$text;
		}
	}
	if (preg_match_all('#yfrog.([a-zA-Z.]{2,5})/([0-9a-zA-Z]+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[2] as $key => $match) {
			$text = "<a href='http://{$matches[0][$key]}'><img src='http://yfrog.{$matches[1][$key]}/{$match}.th.jpg' /></a><br />".$text;
		}
	}
	if (preg_match_all('#twitxr.com/[^ ]+/updates/([\d]+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $key => $match) {
			$thumb = 'http://twitxr.com/thumbnails/'.substr($match, -2).'/'.$match.'_th.jpg';
			$text = "<a href='http://{$matches[0][$key]}'><img src='$thumb' /></a><br />".$text;
		}
	}
	if (preg_match_all('#moblog.net/view/([\d]+)/#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $key => $match) {
			$text = "<a href='http://{$matches[0][$key]}'><img src='moblog/$match' /></a><br />".$text;
		}
	}
	if (preg_match_all('#hellotxt.com/i/([\d\w]+)#i', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $key => $match) {
			$text = "<a href='http://{$matches[0][$key]}'><img src='http://hellotxt.com/image/{$match}.s.jpg' /></a><br />".$text;
		}
	}
	if (preg_match_all('#ts1.in/(\d+)#i', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $key => $match) {
			$text = "<a href='http://{$matches[0][$key]}'><img src='http://ts1.in/mini/{$match}' /></a><br />".$text;
		}
	}
	if (preg_match_all('#moby.to/\??([\w\d]+)#i', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $key => $match) {
			$text = "<a href='http://{$matches[0][$key]}'><img src='mobypicture/{$match}' /></a><br />".$text;
		}
	}
	if (preg_match_all('#tweetphoto.com/(\d+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $key => $match) {
			$text = "<a href='http://{$matches[0][$key]}'><img src='http://TweetPhotoAPI.com/api/TPAPI.svc/json/imagefromurl?size=thumbnail&url=http://tweetphoto.com/{$match}' /></a><br />".$text;
		}
	}
	if (defined('FLICKR_API_KEY')) {
		if(preg_match_all('#flickr.com/[^ ]+/([\d]+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
			foreach ($matches[1] as $key => $match) {
				$text = "<a href='http://{$matches[0][$key]}'><img src='flickr/$match' /></a><br />".$text;
			}
		}
		if(preg_match_all('#flic.kr/p/([\w\d]+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
			foreach ($matches[1] as $key => $match) {
				$id = flickr_decode($match);
				$text = "<a href='http://{$matches[0][$key]}'><img src='flickr/$id' /></a><br />".$text;
			}
		}
	}
	if (defined('MOBYPICTURE_API_KEY') && preg_match_all('#mobypicture.com/\?([a-z0-9]+)#', $tmp, $matches, PREG_PATTERN_ORDER) > 0) {
		foreach ($matches[1] as $key => $match) {
			$text = "<a href='http://{$matches[0][$key]}'><img src='mobypicture/$match' /></a><br />".$text;
		}
	}
	return $text;
}

function generate_thumbnail($query) {
	$id = $query[1];
	if ($id) {
		header('HTTP/1.1 301 Moved Permanently');
		if ($query[0] == 'flickr') {
			$url = "http://api.flickr.com/services/rest/?method=flickr.photos.getSizes&photo_id=$id&api_key=".FLICKR_API_KEY;
			$flickr_xml = twitter_fetch($url);
			if (setting_fetch('browser') == 'mobile') {
				$pattern = '#"(http://.*_t\.jpg)"#';
			} else {
				$pattern = '#"(http://.*_m\.jpg)"#';
			}
			preg_match($pattern, $flickr_xml, $matches);
			header('Location: '. $matches[1]);
		}
		if ($query[0] == 'mobypicture') {
			$url = "http://api.mobypicture.com/?action=getThumbUrl&t={$id}&s=thumbnail&k=".MOBYPICTURE_API_KEY;
			$thumb = twitter_fetch($url);
			header('Location: '. $thumb);
		}
		if ($query[0] == 'moblog') {
			$url = "http://moblog.net/view/{$id}/";
			$html = twitter_fetch($url);
			if (preg_match('#"(/media/[a-zA-Z0-9]/[^"]+)"#', $html, $matches)) {
				$thumb = 'http://moblog.net' . str_replace(array('.j', '.J'), array('_tn.j', '_tn.J'), $matches[1]);
				$pos = strrpos($thumb, '/');
				$thumb = substr($thumb, 0, $pos) . '/thumbs' . substr($thumb, $pos);
			}
			header('Location: '. $thumb);
		}
	}
	exit();
}

function format_interval($timestamp, $granularity = 2) {
	$units = array(
		__("years") => 31536000,
		__("days") => 86400,
		__("hours") => 3600,
		__("min") => 60,
		__("sec") => 1
	);
    $output = '';
	foreach ($units as $key => $value) {
	if ($timestamp >= $value) {
		$output .= ($output ? ' ' : '').floor($timestamp / $value).' '.$key;
		$timestamp %= $value;
		$granularity--;
	}
	if ($granularity == 0) {
		break;
	}
    }
	return $output ? $output : __("0 sec");
}

function twitter_status_page($query) {
	$id = (string) $query[1];
	if (is_numeric($id)) {
		$request = NETPUTWEETS_API."statuses/show/{$id}.json";
		$status = twitter_process($request);
		$content = theme('status', $status);
		if (!$status->user->protected) {
			$thread = twitter_thread_timeline($id);
		}
	if ($thread) {
		$content .= '<p>Conversation View:</p>'.theme('timeline', $thread);
		$content .= "<p>Don't like the thread order? Go to <a href='".BASE_URL."settings'>settings</a> to reverse it. Either way - the dates/times are not always accurate.</p>";
	}
	theme('page', __("Status")." $id", $content);
	}
}

function twitter_thread_timeline($thread_id) {
	$request = NETPUTWEETS_APIS."search/thread/{$thread_id}";
	$tl = twitter_standard_timeline(twitter_fetch($request), 'thread');
	return $tl;
}

function twitter_retweet_page($query) {
	$id = (string) $query[1];
	if (is_numeric($id)) {
		$request = NETPUTWEETS_API."statuses/show/{$id}.json";
		$tl = twitter_process($request);
		$content = theme('retweet', $tl);
		theme('page', __("Retweet"), $content);
	}
}

function twitter_refresh($page = NULL) {
	if (isset($page)) {
		$page = BASE_URL . $page;
	} else {
		$page = $_SERVER['HTTP_REFERER'];
	}
	header('Location: '. $page);
	exit();
}

function twitter_delete_page($query) {
	twitter_ensure_post_action();
	$id = (string) $query[1];
	if (is_numeric($id)) {
		$request = NETPUTWEETS_API."statuses/destroy/{$id}.json?page=".intval($_GET['page']);
		$tl = twitter_process($request, true);
		twitter_refresh('user/'.user_current_username());
	}
}

function twitter_ensure_post_action() {
	if ($_SERVER['REQUEST_METHOD'] !== 'POST') die('Error: Invalid HTTP request method for this action.');
}

function twitter_spam_page($query) {
	twitter_ensure_post_action();
	$user = $query[1];
	$post_data = array("screen_name" => $user);
	$request = NETPUTWEETS_API."report_spam.json";
	twitter_process($request, $post_data);
	twitter_refresh("user/{$user}");
}

function twitter_follow_page($query) {
	$user = $query[1];
	if ($user) {
		if($query[0] == 'follow'){
			$request = NETPUTWEETS_API."friendships/create/{$user}.json";
		} else {
			$request = NETPUTWEETS_API."friendships/destroy/{$user}.json";
		}
		twitter_process($request, true);
		twitter_refresh('friends');
	}
}

function twitter_block_page($query) {
	twitter_ensure_post_action();
	$user = $query[1];
	if ($user) {
		if($query[0] == 'block'){
			$request = NETPUTWEETS_API."blocks/create/{$user}.json";
		} else {
			$request = NETPUTWEETS_API."blocks/destroy/{$user}.json";
		}
		twitter_process($request, true);
		twitter_refresh("user/{$user}");
	}
}

function twitter_confirmation_page($query) {
	// the URL /confirm can be passed parameters like so /confirm/param1/param2/param3 etc.
 	$action = $query[1];
 	$target = $query[2];	//The name of the user we are doing this action on
 	$target_id = $query[3];	//The targets's ID. Needed to check if they are being blocked.
	switch ($action) {
		case 'block':
		if (twitter_block_exists($target_id)) { //Is the target blocked by the user?
			$action = 'unblock';
			$content  = "<p>".__("Are you really sure you want to <strong>Unblock ")."$target</strong>?</p>";
			$content .= __("<ul><li>They will see your updates on their home page if they follow you again.</li><li>You <em>can</em> block them again if you want.</li></ul>");
		} else {
			$content = __("<p>Are you really sure you want to")." <strong>$action $target</strong>?</p>";
			$content .= __("<ul><li>You won't show up in their list of friends</li><li>They won't see your updates on their home page</li><li>They won't be able to follow you</li><li>You <em>can</em> unblock them but you will need to follow them again afterwards</li></ul>");
		}
		break;
		case 'delete':
			$request = NETPUTWEETS_API."statuses/show/$target.json";
			$status = twitter_process($request);
			$parsed = twitter_parse_tags($status->text);
			$content = "<p>".__("Are you really sure you want to delete your tweet?")."</p>";
			$content .= "<ul><li>Tweet: $parsed</li><li>".__("There is no way to undo this action").".</li></ul>";
		break;
		case 'spam':
			$content  = "<p>Are you really sure you want to report <strong>$target</strong> as a spammer?</p>";
			$content .= "<p>They will also be blocked from following you.</p>";
		break;
		}
	$content .= "<form action='".BASE_URL."$action/$target' method='post'><input type='submit' value='Yes' /></form>";
	theme('Page', __("Confirm"), $content);
}

function twitter_friends_page($query) {
	$user = $query[1];
	if (!$user) {
	user_ensure_authenticated();
	$user = user_current_username();
	}
	$request = NETPUTWEETS_API."statuses/friends/{$user}.xml";
	$tl = lists_paginated_process($request);
	$content = theme('followers', $tl);
	theme('page', __("Friends"), $content);
}

function twitter_followers_page($query) {
	$user = $query[1];
	if (!$user) {
	user_ensure_authenticated();
	$user = user_current_username();
	}
	$request = NETPUTWEETS_API."statuses/followers/{$user}.xml";
	$tl = lists_paginated_process($request);
	$content = theme('followers', $tl);
	theme('page', __("Followers"), $content);
}

function twitter_blockings_page($query) {
	$request = NETPUTWEETS_API.'blocks/blocking.json?page='.intval($_GET['page']);
	$tl = twitter_process($request);
	$content = theme('followers', $tl);
	theme('page', __("Blockings"), $content);
}

function twitter_update() {
	twitter_ensure_post_action();
	$status = twitter_url_shorten(stripslashes(trim($_POST['status'])));
	if ($status) {
		$status = setting_fetch('fixedtagspre')." ".$status." ".setting_fetch('fixedtagspost');
		if (function_exists('mb_strlen')) $status = sysSubStr($status, 140, true);
		$request = NETPUTWEETS_API.'statuses/update.json';
		$post_data = array('source' => 'dabr', 'status' => $status);
		$in_reply_to_id = (string) $_POST['in_reply_to_id'];
		if (is_numeric($in_reply_to_id)) {
			$post_data['in_reply_to_status_id'] = $in_reply_to_id;
		}
		$b = twitter_process($request, $post_data);
	}
	twitter_refresh($_POST['from'] ? $_POST['from'] : '');
}

function twitter_retweet($query) {
	twitter_ensure_post_action();
	$id = $query[1];
	if (is_numeric($id)) {
		$request = NETPUTWEETS_API.'statuses/retweet/'.$id.'.xml';
		twitter_process($request, true);
	}
	twitter_refresh($_POST['from'] ? $_POST['from'] : '');
}

function twitter_public_page() {
	$count = setting_fetch('tpp', 20);
	$request = NETPUTWEETS_API."statuses/public_timeline.json?count=$count&page=".intval($_GET['page']);
	$content = theme('status_form');
	$tl = twitter_standard_timeline(twitter_process($request), 'public');
	$content .= theme('timeline', $tl);
	theme('page', __("Public Timeline"), $content);
}

function twitter_replies_page() {
	$count = setting_fetch('tpp', 20);
	$request = NETPUTWEETS_API."statuses/replies.json?count=$count&page=".intval($_GET['page']);
	$tl = twitter_process($request);
	$tl = twitter_standard_timeline($tl, 'replies');
	if (setting_fetch('ort', 'no') == 'yes') {
		$tl += twitter_search('@'.user_current_username());
		krsort($tl);
	}
	$content = theme('status_form');
	$content .= theme('timeline', $tl);
	theme('page', __("Replies"), $content);
}

function twitter_retweets_page() {
	$count = setting_fetch('tpp', 20);
	$request = NETPUTWEETS_API."statuses/retweeted_to_me.json?count=$count&page=".intval($_GET['page']);
	$tl = twitter_process($request);
	$tl = twitter_standard_timeline($tl, 'retweets');
	$content = theme('status_form');
	$content .= theme('timeline', $tl);
	theme('page', __("Retweets"), $content);
}

function twitter_directs_page($query) {
	$action = strtolower(trim($query[1]));
	switch ($action) {
	
	case 'delete':
		$id = $query[2];
		if (!is_numeric($id)) return;
		$request = NETPUTWEETS_API."direct_messages/destroy/$id.json";
		twitter_process($request, true);
		twitter_refresh();

	case 'create':
		$to = $query[2];
		$content = theme('directs_form', $to);
		theme('page', __("Create DM")." $to", $content);
	
	case 'send':
		twitter_ensure_post_action();
		$to = trim(stripslashes($_POST['to']));
		$message = trim(stripslashes($_POST['message']));
		$request = NETPUTWEETS_API.'direct_messages/new.json';
		twitter_process($request, array('user' => $to, 'text' => $message));
		twitter_refresh('directs/sent');
	
	case 'sent':
		$request = NETPUTWEETS_API.'direct_messages/sent.json?page='.intval($_GET['page']);
		$tl = twitter_standard_timeline(twitter_process($request), 'directs_sent');
		$content = theme_directs_menu();
		$content .= theme('timeline', $tl);
		theme('page', __("DM Sent"), $content);

	case 'inbox':
	default:
		$request = NETPUTWEETS_API.'direct_messages.json?page='.intval($_GET['page']);
		$tl = twitter_standard_timeline(twitter_process($request), 'directs_inbox');
		$content = theme_directs_menu();
		$content .= theme('timeline', $tl);
		theme('page', __("DM Inbox"), $content);
	}
}

function theme_directs_menu() {
	return '<p><a href="'.BASE_URL.'directs/create">'.__("Create").'</a> | <a href="'.BASE_URL.'directs/inbox">'.__("Inbox").'</a> | <a href="'.BASE_URL.'directs/sent">'.__("Sent").'</a></p>';
}

function theme_directs_form($to) {
	if ($to) {
		if (friendship_exists($to) != 1) {
			return "<p>$to ".__("is not following you. You cannot send direct message to that guy.")."</p>";
		} else {
			$html_to = __("Sending direct message to")." <b>$to</b><input name='to' value='$to' type='hidden'>";
		}
	} else {
		$html_to = __("To").": <input name='to'><br />".__("Message").": ";
	}
	$content = "<form action='".BASE_URL."directs/send' method='post'>$html_to<br /><textarea name='message' style='width:95%' rows='3' id='message'></textarea><br /><input type='submit' value='".__("Send")."'><span id='remaining'>140</span></form>";
	$content .= js_counter("message");
	return $content;
}

function twitter_search_page() {
	$search_query = $_GET['query'];
	$content = theme('search_form', $search_query);
	if (isset($_POST['query'])) {
		$duration = time() + (3600 * 24 * 365);
        setcookie('search_favourite', $_POST['query'], $duration, WEB_ROOT);
		twitter_refresh('search');
	}
	if (!isset($search_query) && array_key_exists('search_favourite', $_COOKIE)) $search_query = $_COOKIE['search_favourite'];
	if ($search_query) {
		$tl = twitter_search($search_query);
		if ($search_query !== $_COOKIE['search_favourite']) {
			$content .= '<form action="'.BASE_URL.'search/bookmark" method="post"><input type="hidden" name="query" value="'.$search_query.'" /><input type="submit" value="'.__("Save as default search").'" /></form>';
		}
		$content .= theme('timeline', $tl);
	}
	theme('page', __("Search"), $content);
}

function twitter_search($search_query) {
	$page = (int) $_GET['page'];
	if ($page == 0) $page = 1;
	$request = NETPUTWEETS_APIS.'search.json?q=' . urlencode($search_query).'&page='.$page;
	$tl = twitter_process($request);
	$tl = twitter_standard_timeline($tl, 'search');
	return $tl;
}

function twitter_user_page($query) {
	$screen_name = $query[1];
	if ($screen_name) {
		$content = '';
		if ($query[2] == 'reply') {
			$str = __("Reply");
			$in_reply_to_id = (string) $query[3];
			if (is_numeric($in_reply_to_id)) {
				$request = NETPUTWEETS_API."statuses/show/{$in_reply_to_id}.json";
				$status = twitter_process($request);
				$parsed = twitter_parse_tags($status->text);
				$content .= "<p>".__("in reply to")." <b>$screen_name</b>: $parsed</p>";
			}
		} else {
			$str = __("User");
			$in_reply_to_id = 0;
		}
		$user = twitter_user_info($screen_name);
		if (!user_is_current_user($user->screen_name)) {
			$status = "@{$user->screen_name} ";
		} else {
			$status = '';
		}
        $content .= theme('status_form', $status, $in_reply_to_id);
		$content .= theme('user_header', $user);
		if (isset($user->status)) {
			if (($query[2] !== 'reply') || (($query[2] == 'reply') && (setting_fetch('moreinreply') == 'yes'))) {
				$request = NETPUTWEETS_API."statuses/user_timeline.json?screen_name={$screen_name}&page=".intval($_GET['page']);
				$tl = twitter_process($request);
				$tl = twitter_standard_timeline($tl, 'user');
				$content .= theme('timeline', $tl);
			}
		}
		
		theme('page', $str." {$screen_name}", $content);
	} else {
	// TODO: user search screen
	}
}

function twitter_favourites_page($query) {
	$screen_name = $query[1];
	if (!$screen_name) {
		user_ensure_authenticated();
		$screen_name = user_current_username();
	}
	$request = NETPUTWEETS_API."favorites/{$screen_name}.json?page=".intval($_GET['page']);
	$tl = twitter_process($request);
	$tl = twitter_standard_timeline($tl, 'favourites');
	$content = theme('status_form');
	$content .= theme('timeline', $tl);
	theme('page', __("Favourites"), $content);
}

function twitter_mark_favourite_page($query) {
	$id = (string) $query[1];
	if (!is_numeric($id)) return;
	if ($query[0] == 'unfavourite') {
		$request = NETPUTWEETS_API."favorites/destroy/$id.json";
	} else {
		$request = NETPUTWEETS_API."favorites/create/$id.json";
	}
	twitter_process($request, true);
	twitter_refresh();
}

function twitter_home_page() {
	user_ensure_authenticated();
	$count = setting_fetch('tpp', 20);
	$request = NETPUTWEETS_API."statuses/home_timeline.json?count=$count&page=".intval($_GET['page']);
	$tl = twitter_process($request);
	$tl = twitter_standard_timeline($tl, 'friends');
	$content = theme('status_form');
	$content .= theme('timeline', $tl);
	theme('page', __("Home").$page, $content);
}

function twitter_hashtag_page($query) {
	if (isset($query[1])) {
		$hashtag = '#'.$query[1];
		$content = theme('status_form', $hashtag.' ');
		$tl = twitter_search($hashtag);
		$content .= theme('timeline', $tl);
		theme('page', $hashtag, $content);
	} else {
		theme('page', __("Hashtag"), 'Hash hash!');
	}
}

function theme_status_form($text = '', $in_reply_to_id = NULL) {
	if (user_is_authenticated()) return "<form method='post' action='".BASE_URL."update'><input name='status' value='{$text}' maxlength='140' /> <input name='in_reply_to_id' value='{$in_reply_to_id}' type='hidden' /><input type='submit' value='".__("Update")."' /></form>";
}

function theme_status($status) {
	$time_since = theme('status_time_link', $status);
	$parsed = twitter_parse_tags($status->text);
	$actions = theme('action_icons', $status);
	$out = theme('status_form', "@{$status->user->screen_name} ");
	$out .= "<p style='margin-left:10%;'><a href='".BASE_URL."user/{$status->user->screen_name}'>{$status->user->screen_name}</a> $actions $time_since<br />$parsed</p>";
	if (user_is_current_user($status->user->screen_name)) {
		$out .= "<form action='".BASE_URL."delete/{$status->id_str}' method='post'><input type='submit' value='".__("Delete without confirmation")."' /></form>";
	}
	return $out;
}

function theme_retweet($status) {
	$rtsyntax = setting_fetch('rtsyntax', 'RT [User]: [Content]');
	$replace = array(
		"[User]" => "@{$status->user->screen_name}",
		"[Content]" => "{$status->text}",
	);
	$text = str_replace(array_keys($replace),array_values($replace),$rtsyntax);
	$length = strlen($text);
	$from = substr($_SERVER['HTTP_REFERER'], strlen(BASE_URL));
	$content = "<p>".__("Old style editable retweet").":</p><form action='".BASE_URL."update' method='post'><input type='hidden' name='from' value='$from' /><textarea name='status' cols='50' rows='3' id='status' style='width:95%'>$text</textarea><br><input type='submit' value='".__(Retweet)."'><span id='remaining'>" . (140 - $length) ."</span></form>".js_counter("status")."<br />";
	if($status->user->protected == 0) {
		$content.= "<form action='".BASE_URL."twitter-retweet/{$status->id_str}' method='post'>".__("Or")." <input type='hidden' name='from' value='$from' /><input type='submit' value='Twitter ".__("Official Retweet")."'></form>";
	} else {
		$content.= __("This is not well suited to retweet a protected user 's tweet.");
	}
	return $content;
}

function theme_user_header($user) {
	$name = theme('full_name', $user);
	$full_avatar = str_replace('_normal.', '.', $user->profile_image_url);
	$link = theme('external_link', $user->url);
    //$raw_date_joined = strtotime($user->created_at);
    $raw_date_joined = strtotime(str_replace('+0000', '', substr($user->created_at,4)));
	$date_joined = date('Y-m-d', $raw_date_joined);
	$days_on_twitter = (time() - $raw_date_joined) / 86400;
	$tweets_per_day = round($user->statuses_count / $days_on_twitter, 1);
	$out = "<table><tr><td><a href='$full_avatar'>".theme('avatar', $user->profile_image_url, 1)."</a></td><td><b>{$name}</b> <small>";
	if ($user->verified == true) {
		$out .= '<i>'.__("Verified").'</i> ';
	}
	if ($user->protected == true) {
	$out .= '<i>'.__("Private/Protected").'</i>';
	}
	$out .= "<br />".__("Bio").": {$user->description}<br />".__("Link").": {$link}<br />".__("Location").": {$user->location}<br />".__("Joined").": {$date_joined} ($tweets_per_day ".__("Tweets Per Day").")</small><br />";
	if (strtolower($user->screen_name) !== strtolower(user_current_username())) {
		if ($user->following !== true) {
			$out.= "<a href='".BASE_URL."follow/{$user->screen_name}'>".__("Follow")."</a>";
		} else {
			$out.= "<a href='".BASE_URL."unfollow/{$user->screen_name}'>".__("Unfollow")."</a>";
		}
		$out .= " | <a href='".BASE_URL."confirm/block/{$user->screen_name}/{$user->id}'>".__("Block")." | ".__("Unblock")."</a> | <a href='".BASE_URL."confirm/spam/{$user->screen_name}/{$user->id}'>".__('Report Spam')."</a> | ";
	} else {
		$out .= "<a href='".BASE_URL."profile'>".__("Update Profile")."</a> | ";
	}
	$out.= "<a href='".BASE_URL."directs/create/{$user->screen_name}'>".__("Direct Message")."</a> || <b>{$user->statuses_count} ".__("Tweets")."</b> | <a href='".BASE_URL."followers/{$user->screen_name}'>{$user->followers_count} ".__("Followers")."</a> | <a href='".BASE_URL."friends/{$user->screen_name}'>{$user->friends_count} ".__("Friends")."</a> | <a href='".BASE_URL."favourites/{$user->screen_name}'>{$user->favourites_count} ".__("Favourites")."</a> | <a href='".BASE_URL."lists/{$user->screen_name}'>".__("Lists")."</a></td></tr></table>";
	return $out;
}

function theme_avatar($url, $force_large = false) {
	$size = $force_large ? 48 : 24;
	if (setting_fetch('avataro', 'yes') !== 'yes') {
		return "<img class='shead' src='$url' height='$size' width='$size' />";
	} else {
		return '';
	}
}
function theme_status_time_link($status, $is_link = true) {
    $created = str_replace('+0000', '', substr($status->created_at,4));
//    $created = $status->created_at;
	$time = strtotime($created);
    if ($time > 0) {
        if (twitter_date('dmy') == twitter_date('dmy', $time)) {
            //$out = 'now:'.date('His',time());
			$out = format_interval(time() + 5*3600 - $time, 1).__(" ago");
		} else {
			$out = twitter_date('H:i', $time);
		}
	} else {
		$out = $created;
	}
	if ($is_link)
		$out = "<a href='".BASE_URL."status/{$status->id_str}'>$out</a>";
	if ((substr($_GET['q'],0,4) == 'user') || (setting_fetch('browser') == 'touch') || (setting_fetch('browser') == 'desktop') || (setting_fetch('browser') == 'naiping')) {
		return $out;
	} else {
		return strip_tags($out);
	}
}
function twitter_date($format, $timestamp = null) {
    static $offset;
    if (!isset($offset)) {
        $now = date('Y-m-d H:i:s', time());
        $offset = strtotime($now.' +8 hour') - time();
    }
/*	if (!isset($offset)) {
	if (user_is_authenticated()) {
		if (array_key_exists('utc_offset', $_COOKIE)) {
		$offset = $_COOKIE['utc_offset'];
		} else {
		$user = twitter_user_info();
		$offset = $user->utc_offset;
		setcookie('utc_offset', $offset, time() + 3000000, '/');
		}
	} else {
		$offset = 0;
	}
}*/
	if (!isset($timestamp)) {
	$timestamp = time();
	}
	return date($format, $timestamp + $offset);
}
function twitter_standard_timeline($feed, $source) {
	$output = array();
	if (!is_array($feed) && !is_array($feed->results) && $source != 'thread') return $output;
	switch ($source) {
	case 'favourites':
	case 'friends':
	case 'public':
	case 'replies':
	case 'retweets':
	case 'user':
		foreach ($feed as $status) {
		$new = $status;
		if ($new->retweeted_status) {
			$retweet = $new->retweeted_status;
			unset($new->retweeted_status);
			$retweet->retweeted_by = $new;
			$new = $retweet;
		}
		$new->from = $new->user;
		unset($new->user);
		$output[$new->id_str] = $new;
		}
		return $output;
	case 'search':
		foreach ($feed->results as $status) {
		$output[$status->id_str] = (object) array(
            'id' => $status->id,
            'id_str' => $status->id_str,
			'text' => $status->text,
			'source' => strpos($status->source, '&lt;') !== false ? html_entity_decode($status->source) : $status->source,
			'from' => (object) array(
			'id' => $status->from_user_id,
			'screen_name' => $status->from_user,
			'profile_image_url' => $status->profile_image_url,
			),
			'to' => (object) array(
			'id' => $status->to_user_id,
			'screen_name' => $status->to_user,
			),
			'created_at' => $status->created_at,
		);
		}
		return $output;
	
	case 'directs_sent':
	case 'directs_inbox':
		foreach ($feed as $status) {
		$new = $status;
		if ($source == 'directs_inbox') {
			$new->from = $new->sender;
			$new->to = $new->recipient;
		} else {
			$new->from = $new->recipient;
			$new->to = $new->sender;
		}
		unset($new->sender, $new->recipient);
		$new->is_direct = true;
		$output[] = $new;
		}
		return $output;
	
	case 'thread':
		// First pass: extract tweet info from the HTML
		$html_tweets = explode('</li>', $feed);
		foreach ($html_tweets as $tweet) {
		$id = preg_match_one('#msgtxt(\d*)#', $tweet);
		if (!$id) continue;
		$output[$id] = (object) array(
            'id' => $id,
            'id_str' => $id_str,
			'text' => strip_tags(preg_match_one('#</a>: (.*)</span>#', $tweet)),
			'source' => preg_match_one('#>from (.*)</span>#', $tweet),
			'from' => (object) array(
			'id' => preg_match_one('#profile_images/(\d*)#', $tweet),
			'screen_name' => preg_match_one('#twitter.com/([^"]+)#', $tweet),
			'profile_image_url' => preg_match_one('#src="([^"]*)"#' , $tweet),
			),
			'to' => (object) array(
			'screen_name' => preg_match_one('#@([^<]+)#', $tweet),
			),
			'created_at' => str_replace('about', '', preg_match_one('#info">\s(.*)#', $tweet)),
		);
		}
		// Second pass: OPTIONALLY attempt to reverse the order of tweets
		if (setting_fetch('reverse') == 'yes') {
		$first = false;
		foreach ($output as $id => $tweet) {
			$date_string = str_replace('later', '', $tweet->created_at);
			if ($first) {
			$attempt = strtotime("+$date_string");
			if ($attempt == 0) $attempt = time();
			$previous = $current = $attempt - time() + $previous;
			} else {
			$previous = $current = $first = strtotime($date_string);
			}
			$output[$id]->created_at = date('r', $current);
		}
		$output = array_reverse($output);
		}
		return $output;

	default:
		echo "<h1>$source</h1><pre>";
		print_r($feed); die();
	}
}

function preg_match_one($pattern, $subject, $flags = NULL) {
	preg_match($pattern, $subject, $matches, $flags);
	return trim($matches[1]);
}

function twitter_user_info($username = null) {
	if (!$username)
    	$username = user_current_username();
	$request = NETPUTWEETS_API."users/show.json?screen_name=$username";
	$user = twitter_process($request);
	return $user;
}

function theme_timeline($feed) {
	if (count($feed) == 0) return theme('no_tweets');
	$rows = array();
	$page = menu_current_page();
	$date_heading = false;
	foreach ($feed as $status) {
		$time = strtotime($status->created_at);
		if ($time > 0) {
			$date = twitter_date('l jS F Y', strtotime($status->created_at));
			if ($date_heading !== $date) {
				$date_heading = $date;
				$rows[] = array(array(
					'data' => "<small>$date</small>",
					'colspan' => 3
				));
			}
		} else {
			$date = $status->created_at;
		}
	$text = twitter_parse_tags($status->text);
	if (setting_fetch('buttontime', 'yes') == 'yes') {
		$link = theme('status_time_link', $status, !$status->is_direct);
	}
	$actions = theme('action_icons', $status);
	$avatar = theme('avatar', $status->from->profile_image_url);
	if (setting_fetch('buttonfrom', 'yes') == 'yes') {
		if ((substr($_GET['q'],0,4) == 'user') || (setting_fetch('browser') == 'touch') || (setting_fetch('browser') == 'desktop') || (setting_fetch('browser') == 'naiping')) {
			$source = $status->source ? (" ".__("from")." {$status->source}") : '';
		}else{
			$source = $status->source ? (" ".__("from")." ".strip_tags($status->source) ."") : '';
		}
	} else {
		$source = NULL;
	}
	if ($status->in_reply_to_status_id_str) {
		$replyto = __("in reply to")." <a href='status/{$status->in_reply_to_status_id_str}'>{$status->in_reply_to_screen_name}</a>";
	} else {
		$replyto = null;
	}

	if (setting_fetch('buttonend') == 'yes') {
		$html = "<b class='suser'><a href='user/{$status->from->screen_name}'>{$status->from->screen_name}</a></b> <span class='stext'>{$text}</span> <small class='sbutton'>$actions $link $source $replyto</small>";
	} else {
		$html = "<b class='suser'><a href='user/{$status->from->screen_name}'>{$status->from->screen_name}</a></b> <small class='sbutton'>$actions $link</small><br /><span class='stext'>{$text}</span> <small class='sbutton'>$source $replyto</small>";
	}

	if ($status->retweeted_by) {
		$retweeted_by = $status->retweeted_by->user->screen_name;
		$html .= " <small class='sretweet'>".__("retweeted by")." <a href='user/{$retweeted_by}'>{$retweeted_by}</a> ".__("<span style='display:none;'>zhuanfa</span>")."</small>";
	}
	$row = array($html);

	if ($page != 'user' && $avatar) {
		array_unshift($row, $avatar);
	}
	if ($page != 'replies' && twitter_is_reply($status)) {
		$row = array('class' => 'reply', 'data' => $row);
	}
	$rows[] = $row;
	}
	$content = theme('table', array(), $rows, array('class' => 'timeline'));
	if (setting_fetch('browser') <> 'blackberry'){
		if (count($feed) >= 15) {
			$content .= theme('pagination');
		}
	}
	return $content;
}

function twitter_is_reply($status) {
	if (!user_is_authenticated()) {
	return false;
	}
	$user = user_current_username();
	return preg_match("#@$user#i", $status->text);
}

function theme_followers($feed, $hide_pagination = false) {
	$rows = array();
	if (count($feed) == 0 || $feed == '[]') return '<p>'.__("No users to display.").'</p>';
	foreach ($feed->users->user as $user) {
	$name = theme('full_name', $user);
	$rows[] = array(
		theme('avatar', $user->profile_image_url),
		"{$name} - {$user->location}<small><br />{$user->description}</small>",
	);
	}
	$content = theme('table', array(), $rows, array('class' => 'followers'));
	if (setting_fetch('browser') <> 'blackberry'){
		if (!$hide_pagination) {
			$content .= theme('list_pagination', $feed);
		}
	}
	return $content;
}

function theme_full_name($user) {
	$name = "<a href='user/{$user->screen_name}'>{$user->screen_name}</a>";
	if ($user->name && $user->name != $user->screen_name) {
	$name .= " ({$user->name})";
	}
	return $name;
}

function theme_no_tweets() {
	return '<p>'.__("No tweets to display.").'</p>';
}

function theme_search_results($feed) {
	$rows = array();
	foreach ($feed->results as $status) {
		$text = twitter_parse_tags($status->text);
		$link = theme('status_time_link', $status);
		$actions = theme('action_icons', $status);
		$row = array(
			theme('avatar', $status->profile_image_url),
			"<a href='".BASE_URL."user/{$status->from_user}'>{$status->from_user}</a> $actions - {$link}<br />{$text}",
		);
		if (twitter_is_reply($status)) {
			$row = array('class' => 'reply', 'data' => $row);
		}
		$rows[] = $row;
	}
	$content = theme('table', array(), $rows, array('class' => 'timeline'));
	if (setting_fetch('browser') <> 'blackberry'){
		$content .= theme('pagination');
	}
	return $content;
}

function theme_search_form($query) {
	$query = stripslashes(htmlspecialchars($query));
	return "<form action='".BASE_URL."search' method='GET'><input name='query' value=\"$query\" /><input type='submit' value='".__("Search")."' /></form>";
}

function theme_external_link($url) {
	if (setting_fetch('longurl') == 'yes') {
		$lurl = long_url($url);
	} else {
		$lurl = $url;
	}
	if (setting_fetch('linktrans') == 'yes') {
		return "<a href='$lurl'>[link]</a>";
	} else {
		return "<a href='$lurl'>$lurl</a>";
	}
}
function theme_pagination() {
	$page = intval($_GET['page']);
	if (preg_match('#&q(.*)#', $_SERVER['QUERY_STRING'], $matches)) {
		$query = $matches[0];
	}
	if ($page == 0) $page = 1;
	$ht = ( BASE_URL == BASE_URF ? "{$_GET['q']}?" : "index.php?q={$_GET['q']}&");
	$links[] = "<a href='".BASE_URL.$ht."page=".($page+1)."$query' accesskey='9'>".__("Older")."</a> 9";
	if ($page > 1) $links[] = "<a href='".BASE_URL."{$_GET['q']}?page=".($page-1)."$query' accesskey='8'>".__("Newer")."</a> 8";
	return '<p class="pagination">'.implode(' | ', $links).'</p>';
}
function theme_action_icons($status) {
	$from = $status->from->screen_name;
	$actions = array();
	if (!$status->is_direct) {
		if (setting_fetch('buttonre', 'yes') == 'yes') {
			$actions[] = theme('action_icon', BASE_URL."user/{$from}/reply/{$status->id_str}", 'images/reply.png', __('@'));
		}
	}
		if (!user_is_current_user($from)) {
			$actions[] = theme('action_icon', BASE_URL."directs/create/{$from}", 'images/dm.png', __('DM'));
		}
	if (!$status->is_direct) {
		if (setting_fetch('buttonfav', 'yes') == 'yes') {
			if ($status->favorited == '1') {
				$actions[] = theme('action_icon', BASE_URL."unfavourite/{$status->id_str}", 'images/star.png', __('UNFAV'));
			} else {
				$actions[] = theme('action_icon', BASE_URL."favourite/{$status->id_str}", 'images/star_grey.png', __('FAV'));
			}
		}
		if (setting_fetch('buttonrt', 'yes') == 'yes') {
			$actions[] = theme('action_icon', BASE_URL."retweet/{$status->id_str}", 'images/retweet.png', __('RT'));
		}
		if (setting_fetch('buttondel', 'yes') == 'yes') {
			if (user_is_current_user($from)) {
				$actions[] = theme('action_icon', BASE_URL."confirm/delete/{$status->id_str}", 'images/trash.gif', __('DEL'));
			}
		}
	} else {
		$actions[] = theme('action_icon', BASE_URL."directs/delete/{$status->id_str}", 'images/trash.gif', __('DEL'));
	}
	return implode(' ', $actions);
}
function theme_action_icon($url, $image_url, $text) {
	if (setting_fetch('buttonintext', 'yes') == 'yes') {
		return "<a href='$url'>$text</a>";
	} else {
		return "<a href='$url'><img src='$image_url' /></a>";
	}
}
?>
